﻿namespace TestTool.GUI.Controls.Device
{
    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Drawing;
    using System.IO;
    using System.Linq;
    using System.Runtime.CompilerServices;
    using System.Windows.Forms;
    using TestTool.GUI.Controllers;
    using TestTool.GUI.Controls;
    using TestTool.GUI.Data;
    using TestTool.GUI.Enums;
    using TestTool.GUI.Utils;
    using TestTool.GUI.Views;

    internal class RequestsPage : Page, IRequestsView, IView
    {
        private RequestsController _controller;
        private Dictionary<RequestFolder, TreeNode> _folderNodes = new Dictionary<RequestFolder, TreeNode>();
        private Dictionary<RequestFile, TreeNode> _requestNodes = new Dictionary<RequestFile, TreeNode>();
        private Button btnAddRequestToTemplates;
        private Button btnDelete;
        private Button btnRequestFile;
        private Button btnSendRequest;
        private ComboBox cmbService;
        private IContainer components;
        private Label lblRequest;
        private Label lblRequestFile;
        private Label lblResponse;
        private Label lblService;
        private Label lblServiceAddress;
        private Label lblTemplates;
        private SplitContainer scRequests;
        private SplitContainer scTraffic;
        private TextBox tbRequest;
        private TextBox tbRequestFile;
        private TextBox tbResponse;
        private TextBox tbServiceAddress;
        private TreeView tvTemplates;

        public RequestsPage()
        {
            this.InitializeComponent();
            this._controller = new RequestsController(this);
            this.InitPage();
        }

        public void AddFile(RequestFile file, RequestFolder parentFolder)
        {
            if (parentFolder == null)
            {
                this.AddRequestNode(null, file);
            }
            else
            {
                TreeNode parent = this._folderNodes[parentFolder];
                this.AddRequestNode(parent, file);
            }
        }

        public void AddFolder(RequestFolder folder, RequestFolder parentFolder)
        {
            if (parentFolder == null)
            {
                this.AddFolderNode(null, folder);
            }
            else
            {
                TreeNode parent = this._folderNodes[parentFolder];
                this.AddFolderNode(parent, folder);
            }
        }

        private void AddFolderNode(TreeNode parent, RequestFolder folder)
        {
            TreeNode node = new TreeNode(folder.Name)
            {
                Tag = folder
            };
            this._folderNodes.Add(folder, node);
            if (parent == null)
            {
                this.tvTemplates.Nodes.Add(node);
            }
            else
            {
                parent.Nodes.Add(node);
            }
            foreach (RequestFolder folder2 in folder.Folders)
            {
                this.AddFolderNode(node, folder2);
            }
            foreach (RequestFile file in folder.Requests)
            {
                this.AddRequestNode(node, file);
            }
        }

        private void AddRequestNode(TreeNode parent, RequestFile file)
        {
            TreeNode node = new TreeNode(file.FileName)
            {
                Tag = file
            };
            if (parent != null)
            {
                parent.Nodes.Add(node);
            }
            else
            {
                this.tvTemplates.Nodes.Add(node);
            }
            this._requestNodes.Add(file, node);
        }

        private void btnAddRequestToTemplates_Click(object sender, EventArgs e)
        {
            this.SaveRequest();
        }

        private void btnDelete_Click(object sender, EventArgs e)
        {
            TreeNode selectedNode = this.tvTemplates.SelectedNode;
            if (selectedNode != null)
            {
                RequestFile tag = selectedNode.Tag as RequestFile;
                if ((tag != null) && (MessageBox.Show("Request will be deleted. Continue?", "Question", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes))
                {
                    try
                    {
                        this._controller.DeleteRequest(tag);
                        this.tvTemplates.Nodes.Remove(selectedNode);
                    }
                    catch (Exception exception)
                    {
                        this.ShowError(string.Format("Request could not be deleted: {0}", exception.Message));
                    }
                }
            }
        }

        private void btnRequestFile_Click(object sender, EventArgs e)
        {
            OpenFileDialog dialog = new OpenFileDialog
            {
                CheckFileExists = true,
                Multiselect = false,
                DefaultExt = "xml"
            };
            if (dialog.ShowDialog() == DialogResult.OK)
            {
                string fileName = dialog.FileName;
                this.tbRequestFile.Text = fileName;
                FileStream stream = File.OpenRead(fileName);
                TextReader reader = new StreamReader(stream);
                string request = reader.ReadToEnd();
                this.tbRequest.Text = this._controller.ApplySecurity(request);
                reader.Close();
                stream.Close();
                stream.Dispose();
            }
        }

        private void btnSendRequest_Click(object sender, EventArgs e)
        {
            this._controller.SendRequest();
        }

        private void cmbService_SelectedIndexChanged(object sender, EventArgs e)
        {
            ServiceListItem selectedItem = (ServiceListItem)this.cmbService.SelectedItem;
            this._controller.SelectService(selectedItem.Service);
        }

        public void DeleteFile(RequestFile file, RequestFolder parentFolder)
        {
            TreeNode node = this._requestNodes[file];
            if (parentFolder == null)
            {
                this.tvTemplates.Nodes.Remove(node);
            }
            else
            {
                TreeNode node2 = this._folderNodes[parentFolder];
                node2.Nodes.Remove(node);
            }
        }

        public void DisplayFolders(RequestFolder rootFolder)
        {
            this.tvTemplates.Nodes.Clear();
            this._folderNodes.Clear();
            this._requestNodes.Clear();
            foreach (RequestFolder folder in rootFolder.Folders)
            {
                this.AddFolderNode(null, folder);
            }
            foreach (RequestFile file in rootFolder.Requests)
            {
                this.AddRequestNode(null, file);
            }
        }

        public void DisplayResponse(string response)
        {
            base.BeginInvoke(new Action(() => this.tbResponse.Text = response));
        }

        protected override void Dispose(bool disposing)
        {
            if (disposing && (this.components != null))
            {
                this.components.Dispose();
            }
            base.Dispose(disposing);
        }

        public override IController GetController()
        {
            return this._controller;
        }

        private void InitializeComponent()
        {
            this.scRequests = new SplitContainer();
            this.lblTemplates = new Label();
            this.tvTemplates = new TreeView();
            this.btnDelete = new Button();
            this.scTraffic = new SplitContainer();
            this.tbRequest = new TextBox();
            this.lblRequest = new Label();
            this.tbResponse = new TextBox();
            this.lblResponse = new Label();
            this.cmbService = new ComboBox();
            this.btnSendRequest = new Button();
            this.lblServiceAddress = new Label();
            this.tbServiceAddress = new TextBox();
            this.lblService = new Label();
            this.btnAddRequestToTemplates = new Button();
            this.tbRequestFile = new TextBox();
            this.lblRequestFile = new Label();
            this.btnRequestFile = new Button();
            this.scRequests.Panel1.SuspendLayout();
            this.scRequests.Panel2.SuspendLayout();
            this.scRequests.SuspendLayout();
            this.scTraffic.Panel1.SuspendLayout();
            this.scTraffic.Panel2.SuspendLayout();
            this.scTraffic.SuspendLayout();
            base.SuspendLayout();
            this.scRequests.Dock = DockStyle.Fill;
            this.scRequests.Location = new Point(0, 0);
            this.scRequests.Name = "scRequests";
            this.scRequests.Panel1.Controls.Add(this.lblTemplates);
            this.scRequests.Panel1.Controls.Add(this.tvTemplates);
            this.scRequests.Panel2.Controls.Add(this.btnDelete);
            this.scRequests.Panel2.Controls.Add(this.scTraffic);
            this.scRequests.Panel2.Controls.Add(this.cmbService);
            this.scRequests.Panel2.Controls.Add(this.btnSendRequest);
            this.scRequests.Panel2.Controls.Add(this.lblServiceAddress);
            this.scRequests.Panel2.Controls.Add(this.tbServiceAddress);
            this.scRequests.Panel2.Controls.Add(this.lblService);
            this.scRequests.Panel2.Controls.Add(this.btnAddRequestToTemplates);
            this.scRequests.Panel2.Controls.Add(this.tbRequestFile);
            this.scRequests.Panel2.Controls.Add(this.lblRequestFile);
            this.scRequests.Panel2.Controls.Add(this.btnRequestFile);
            this.scRequests.Size = new Size(0x335, 0x1e7);
            this.scRequests.SplitterDistance = 0x110;
            this.scRequests.TabIndex = 5;
            this.lblTemplates.AutoSize = true;
            this.lblTemplates.Location = new Point(6, 9);
            this.lblTemplates.Name = "lblTemplates";
            this.lblTemplates.Size = new Size(0x3b, 13);
            this.lblTemplates.TabIndex = 1;
            this.lblTemplates.Text = "Templates:";
            this.tvTemplates.Anchor = AnchorStyles.Right | AnchorStyles.Left | AnchorStyles.Bottom | AnchorStyles.Top;
            this.tvTemplates.HideSelection = false;
            this.tvTemplates.Location = new Point(3, 0x21);
            this.tvTemplates.Name = "tvTemplates";
            this.tvTemplates.Size = new Size(0x10a, 0x1c3);
            this.tvTemplates.TabIndex = 4;
            this.tvTemplates.AfterSelect += new TreeViewEventHandler(this.tvTemplates_AfterSelect);
            this.btnDelete.Location = new Point(6, 0x55);
            this.btnDelete.Name = "btnDelete";
            this.btnDelete.Size = new Size(0x60, 0x17);
            this.btnDelete.TabIndex = 20;
            this.btnDelete.Text = "Delete Request";
            this.btnDelete.UseVisualStyleBackColor = true;
            this.btnDelete.Click += new EventHandler(this.btnDelete_Click);
            this.scTraffic.Anchor = AnchorStyles.Right | AnchorStyles.Left | AnchorStyles.Bottom | AnchorStyles.Top;
            this.scTraffic.Location = new Point(0, 0x72);
            this.scTraffic.Name = "scTraffic";
            this.scTraffic.Panel1.Controls.Add(this.tbRequest);
            this.scTraffic.Panel1.Controls.Add(this.lblRequest);
            this.scTraffic.Panel2.Controls.Add(this.tbResponse);
            this.scTraffic.Panel2.Controls.Add(this.lblResponse);
            this.scTraffic.Size = new Size(0x215, 0x175);
            this.scTraffic.SplitterDistance = 0x108;
            this.scTraffic.TabIndex = 0x13;
            this.tbRequest.Anchor = AnchorStyles.Right | AnchorStyles.Left | AnchorStyles.Bottom | AnchorStyles.Top;
            this.tbRequest.Location = new Point(6, 0x11);
            this.tbRequest.Multiline = true;
            this.tbRequest.Name = "tbRequest";
            this.tbRequest.ScrollBars = ScrollBars.Both;
            this.tbRequest.Size = new Size(0xff, 0x161);
            this.tbRequest.TabIndex = 12;
            this.tbRequest.WordWrap = false;
            this.lblRequest.AutoSize = true;
            this.lblRequest.Location = new Point(3, 0);
            this.lblRequest.Name = "lblRequest";
            this.lblRequest.Size = new Size(50, 13);
            this.lblRequest.TabIndex = 2;
            this.lblRequest.Text = "Request:";
            this.tbResponse.Anchor = AnchorStyles.Right | AnchorStyles.Left | AnchorStyles.Bottom | AnchorStyles.Top;
            this.tbResponse.Location = new Point(5, 0x11);
            this.tbResponse.Multiline = true;
            this.tbResponse.Name = "tbResponse";
            this.tbResponse.ReadOnly = true;
            this.tbResponse.ScrollBars = ScrollBars.Both;
            this.tbResponse.Size = new Size(0x103, 0x161);
            this.tbResponse.TabIndex = 13;
            this.tbResponse.WordWrap = false;
            this.lblResponse.AutoSize = true;
            this.lblResponse.Location = new Point(3, 0);
            this.lblResponse.Name = "lblResponse";
            this.lblResponse.Size = new Size(0x3a, 13);
            this.lblResponse.TabIndex = 4;
            this.lblResponse.Text = "Response:";
            this.cmbService.Anchor = AnchorStyles.Right | AnchorStyles.Left | AnchorStyles.Top;
            this.cmbService.DisplayMember = "DisplayName";
            this.cmbService.DropDownStyle = ComboBoxStyle.DropDownList;
            this.cmbService.FormattingEnabled = true;
            this.cmbService.Location = new Point(0x5f, 6);
            this.cmbService.Name = "cmbService";
            this.cmbService.Size = new Size(0x1bb, 0x15);
            this.cmbService.TabIndex = 6;
            this.cmbService.ValueMember = "Service";
            this.cmbService.SelectedIndexChanged += new EventHandler(this.cmbService_SelectedIndexChanged);
            this.btnSendRequest.Anchor = AnchorStyles.Right | AnchorStyles.Top;
            this.btnSendRequest.Location = new Point(0x1be, 0x55);
            this.btnSendRequest.Name = "btnSendRequest";
            this.btnSendRequest.Size = new Size(0x5d, 0x17);
            this.btnSendRequest.TabIndex = 11;
            this.btnSendRequest.Text = "Send Request";
            this.btnSendRequest.UseVisualStyleBackColor = true;
            this.btnSendRequest.Click += new EventHandler(this.btnSendRequest_Click);
            this.lblServiceAddress.AutoSize = true;
            this.lblServiceAddress.Location = new Point(3, 0x24);
            this.lblServiceAddress.Name = "lblServiceAddress";
            this.lblServiceAddress.Size = new Size(0x57, 13);
            this.lblServiceAddress.TabIndex = 0x11;
            this.lblServiceAddress.Text = "Service Address:";
            this.tbServiceAddress.Anchor = AnchorStyles.Right | AnchorStyles.Left | AnchorStyles.Top;
            this.tbServiceAddress.Location = new Point(0x60, 0x21);
            this.tbServiceAddress.Name = "tbServiceAddress";
            this.tbServiceAddress.Size = new Size(0x1bb, 20);
            this.tbServiceAddress.TabIndex = 7;
            this.lblService.AutoSize = true;
            this.lblService.Location = new Point(3, 9);
            this.lblService.Name = "lblService";
            this.lblService.Size = new Size(0x2e, 13);
            this.lblService.TabIndex = 15;
            this.lblService.Text = "Service:";
            this.btnAddRequestToTemplates.Anchor = AnchorStyles.Right | AnchorStyles.Top;
            this.btnAddRequestToTemplates.Location = new Point(0x115, 0x55);
            this.btnAddRequestToTemplates.Name = "btnAddRequestToTemplates";
            this.btnAddRequestToTemplates.Size = new Size(0xa3, 0x17);
            this.btnAddRequestToTemplates.TabIndex = 10;
            this.btnAddRequestToTemplates.Text = "Add Request To Templates";
            this.btnAddRequestToTemplates.UseVisualStyleBackColor = true;
            this.btnAddRequestToTemplates.Click += new EventHandler(this.btnAddRequestToTemplates_Click);
            this.tbRequestFile.Anchor = AnchorStyles.Right | AnchorStyles.Left | AnchorStyles.Top;
            this.tbRequestFile.Location = new Point(0x60, 0x3b);
            this.tbRequestFile.Name = "tbRequestFile";
            this.tbRequestFile.ReadOnly = true;
            this.tbRequestFile.Size = new Size(0x199, 20);
            this.tbRequestFile.TabIndex = 8;
            this.lblRequestFile.AutoSize = true;
            this.lblRequestFile.Location = new Point(3, 0x3f);
            this.lblRequestFile.Name = "lblRequestFile";
            this.lblRequestFile.Size = new Size(0x45, 13);
            this.lblRequestFile.TabIndex = 2;
            this.lblRequestFile.Text = "Request File:";
            this.btnRequestFile.Anchor = AnchorStyles.Right | AnchorStyles.Top;
            this.btnRequestFile.Location = new Point(0x1ff, 0x38);
            this.btnRequestFile.Name = "btnRequestFile";
            this.btnRequestFile.Size = new Size(0x1c, 0x17);
            this.btnRequestFile.TabIndex = 9;
            this.btnRequestFile.Text = "...";
            this.btnRequestFile.UseVisualStyleBackColor = true;
            this.btnRequestFile.Click += new EventHandler(this.btnRequestFile_Click);
            base.AutoScaleDimensions = new SizeF(6f, 13f);
            base.AutoScaleMode = AutoScaleMode.Font;
            base.Controls.Add(this.scRequests);
            base.Name = "RequestsPage";
            base.Size = new Size(0x335, 0x1e7);
            this.scRequests.Panel1.ResumeLayout(false);
            this.scRequests.Panel1.PerformLayout();
            this.scRequests.Panel2.ResumeLayout(false);
            this.scRequests.Panel2.PerformLayout();
            this.scRequests.ResumeLayout(false);
            this.scTraffic.Panel1.ResumeLayout(false);
            this.scTraffic.Panel1.PerformLayout();
            this.scTraffic.Panel2.ResumeLayout(false);
            this.scTraffic.Panel2.PerformLayout();
            this.scTraffic.ResumeLayout(false);
            base.ResumeLayout(false);
        }

        private void InitPage()
        {
            List<ServiceListItem> list = new List<ServiceListItem> {
                new ServiceListItem(DutService.DeviceManagement),
                new ServiceListItem(DutService.Media),
                new ServiceListItem(DutService.PTZ),
                new ServiceListItem(DutService.Event)
            };
            this.cmbService.DataSource = list;
            this.cmbService.DisplayMember = "DisplayName";
        }

        private RequestFile SaveRequest()
        {
            TreeNode selectedNode = this.tvTemplates.SelectedNode;
            string path = null;
            if (selectedNode != null)
            {
                RequestFolder tag = selectedNode.Tag as RequestFolder;
                if (tag != null)
                {
                    path = tag.Path;
                }
                else
                {
                    TreeNode parent = selectedNode.Parent;
                    if (parent != null)
                    {
                        tag = parent.Tag as RequestFolder;
                        if (tag != null)
                        {
                            path = tag.Path;
                        }
                    }
                }
            }
            if (path == null)
            {
                path = this._controller.RequestsRootPath;
            }
            SaveFileDialog dialog = new SaveFileDialog
            {
                InitialDirectory = path,
                AddExtension = true,
                Filter = "XML files | *.xml",
                DefaultExt = "xml",
                OverwritePrompt = true
            };
            RequestFile file = null;
            if (dialog.ShowDialog() == DialogResult.OK)
            {
                string fileName = dialog.FileName;
                try
                {
                    file = this._controller.SaveRequest(fileName, this.tbRequest.Text);
                }
                catch (Exception)
                {
                    this.ShowError("An error occured during saving the request. File was not saved.");
                }
            }
            return file;
        }

        public override void SwitchToState(TestTool.GUI.Enums.ApplicationState state)
        {
            Action method = null;
            Action action2 = null;
            Control[] controls = new Control[] { this.cmbService, this.tbServiceAddress, this.tvTemplates, this.btnAddRequestToTemplates, this.btnSendRequest, this.btnRequestFile, this.tbRequestFile, this.tbRequest, this.tbResponse };
            if (state.IsActive())
            {
                if (method == null)
                {
                    method = delegate
                    {
                        this.DisableControls(controls);
                        this.btnDelete.Enabled = false;
                    };
                }
                base.BeginInvoke(method);
            }
            else
            {
                if (action2 == null)
                {
                    action2 = delegate
                    {
                        this.EnableControls(controls);
                        TreeNode selectedNode = this.tvTemplates.SelectedNode;
                        if (selectedNode != null)
                        {
                            RequestFile tag = selectedNode.Tag as RequestFile;
                            this.btnDelete.Enabled = tag != null;
                        }
                        else
                        {
                            this.btnDelete.Enabled = false;
                        }
                    };
                }
                base.BeginInvoke(action2);
            }
        }

        private void tvTemplates_AfterSelect(object sender, TreeViewEventArgs e)
        {
            TreeNode selectedNode = this.tvTemplates.SelectedNode;
            if (selectedNode != null)
            {
                RequestFile tag = selectedNode.Tag as RequestFile;
                this.btnDelete.Enabled = tag != null;
                if (tag != null)
                {
                    try
                    {
                        this.tbRequest.Text = this._controller.ApplySecurity(tag.Content);
                    }
                    catch (Exception)
                    {
                        if (MessageBox.Show("An error occurred during loading the file. Remove this request from the hierarchy?", "Unable to load request", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes)
                        {
                            selectedNode.Remove();
                        }
                    }
                    return;
                }
            }
            this.btnDelete.Enabled = false;
            this.tbRequest.Text = string.Empty;
        }

        internal RequestsController Controller
        {
            get
            {
                return this._controller;
            }
        }

        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public string Request
        {
            get
            {
                return this.tbRequest.Text;
            }
            set
            {
                this.tbRequest.Text = value;
            }
        }

        public DutService Service
        {
            get
            {
                ServiceListItem selectedItem = (ServiceListItem)this.cmbService.SelectedItem;
                return selectedItem.Service;
            }
            set
            {
                List<ServiceListItem> dataSource = (List<ServiceListItem>)this.cmbService.DataSource;
                this.cmbService.SelectedItem = (from i in dataSource
                                                where i.Service == value
                                                select i).FirstOrDefault<ServiceListItem>();
            }
        }

        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public string ServiceAddress
        {
            get
            {
                return this.tbServiceAddress.Text;
            }
            set
            {
                this.tbServiceAddress.Text = value;
            }
        }

        private class ServiceListItem
        {
            public ServiceListItem(DutService service)
            {
                this.Service = service;
                switch (service)
                {
                    case DutService.DeviceManagement:
                        this.DisplayName = "Device Management";
                        return;

                    case DutService.Media:
                        this.DisplayName = "Media";
                        return;

                    case DutService.PTZ:
                        this.DisplayName = "PTZ";
                        return;

                    case DutService.Event:
                        this.DisplayName = "Event";
                        return;
                }
            }

            public string DisplayName { get; private set; }

            public DutService Service { get; private set; }
        }
    }
}

